﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Word = Microsoft.Office.Interop.Word;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Word;
using System.Collections;
using System.Windows.Forms;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Xml;
using System.IO;

namespace SharePointWiki
{
    public partial class ThisAddIn
    {
        Sharepoint_Lists.ListsSoapClient sp;
        Sharepoint_Images.ImagingSoapClient imag;
        Preferences _preferences;
        String _password = "";

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            //sp.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
        }

        public List<string> getSpLists(string ServerTemplateID)
        {
            List<string> WikiIDs;
            WikiIDs = new List<string>();

            setupWebServices();
            XElement lists = sp.GetListCollection();
            foreach (XElement list in lists.Elements())
            {
                string baseType = list.Attribute("BaseType").Value;
                string ServerTemplate = list.Attribute("ServerTemplate").Value;
                if (ServerTemplate == ServerTemplateID)
                    WikiIDs.Add(list.Attribute("ID").Value + " (" + list.Attribute("Title").Value + ")");
            }
            return WikiIDs;
        }

        public void setupWebServices()
        {
            if (sp != null && imag!=null)
                return;

            string username = _preferences.txt_username.Text;
            string domain = _preferences.txt_domain.Text;
            if(_password=="")
            {
                _password = _preferences.txt_password.Text;
                if(_password=="")
                { 
                    Password pwd = new Password();
                    pwd.OnPasswordSet += pwd_OnPasswordSet;
                    pwd.ShowDialog();
                    return;
                }
            }
            sp = new Sharepoint_Lists.ListsSoapClient("ListsSoap", ManageFinalSlash(true, getSiteUrl()) + "_vti_bin/Lists.asmx");
            imag = new Sharepoint_Images.ImagingSoapClient("ImagingSoap", ManageFinalSlash(true, getSiteUrl()) + "_vti_bin/Imaging.asmx");
            sp.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(username, _password, domain);
            sp.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;
            imag.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(username, _password, domain);
            imag.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;
        }

        void pwd_OnPasswordSet(string password)
        {
            _password = password;
            setupWebServices();
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }

        private string getImageListName()
        {
            setupPreferences(_preferences.cmb_wikiImageList.Text);
            return _preferences.cmb_wikiImageList.Text;
            //return "WikiImages"; // WikiImageLibrary
        }

        private string getWikiListId()
        {
            return Preferences.GetIdOfListId(_preferences.getWikiLists(), lastWikiListSetted);
        }

        private string lastWikiListSetted="";
        private string getTitel(Word.Selection selection)
        {
            newWiki newW = new newWiki(_preferences);
            if(selection!=null)
            {
                string x = selection.Paragraphs.First.Range.Text.Replace('\r', ' ').Trim();
                //string x = selection.Text;
                //if(x.IndexOf(Environment.NewLine)>=0)
                //    x = x.Substring(0, x.IndexOf(Environment.NewLine));

                newW.cmbWikiList.Text = lastWikiListSetted;
                newW.txt_wikititle.Text = x;
            }
            if(newW.ShowDialog()== DialogResult.OK)
            {
                lastWikiListSetted = newW.cmbWikiList.Text;
                return newW.txt_wikititle.Text;
            }
            return null;
        }

        private string getSiteUrl()
        {
            setupPreferences(_preferences.txt_site.Text);
            return _preferences.txt_site.Text;
        }

        private void setupPreferences(string value)
        {
            if (_preferences.cmb_wikiImageList.Text == "")
            {
                MessageBox.Show("Setup Preferences first!");
                _preferences.ShowDialog();
            }
        }

        private string getListName(string Id)
        {
            setupWebServices();

            XElement x = sp.GetList(Id);
            foreach (XAttribute xa in x.Attributes("Title"))
                return xa.Value;
            return "";
        }

        private string getRootImageFolder(Boolean withslash)
        {
            setupPreferences(_preferences.txt_wikiImageRootFolder.Text);

            string parent = _preferences.txt_wikiImageRootFolder.Text;
            if (!string.IsNullOrEmpty(parent))
                parent = ManageFinalSlash(withslash, parent);
            else
                parent = "";

            parent = parent + ManageFinalSlash(withslash, getListName(getWikiListId()));

            return parent;
        }

        private static string ManageFinalSlash(Boolean withslash, string parent)
        {
            if (withslash && !parent.EndsWith("/") && !parent.EndsWith(@"\") && parent != "")
                parent += "/";
            if (!withslash && (parent.EndsWith("/") || parent.EndsWith(@"\")))
                parent = parent.Substring(0, parent.Length - 1);
            return parent;
        }
        private string getRootImageFolder()
        {
            return getRootImageFolder(true);
        }

        internal void exportToWiki()
        {
            if(_preferences==null)
               _preferences = new Preferences(this);

            Microsoft.Office.Tools.Word.Document vstoDocument = Globals.Factory.GetVstoObject(this.Application.ActiveDocument);


            Word.Selection selection = this.Application.Selection;

            //XElement x = sp.GetListCollection();
            try {
                string f = getTitel(selection);
                if(!String.IsNullOrEmpty(f))
                {
                    try {
                        setupWebServices();

                        // AddWikiPage throws always exception.. :-(
                        sp.AddWikiPage(getWikiListId(), f + ".aspx", convertCSS(getHTML(selection, f)));
                    }
                    catch { }
                    MessageBox.Show("Wiki " + f + " created.");
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show(getExceptionDetail(ex));
            }
        }

        private void createFolder(string folder, string parent)
        {
            string CreateSubFolder = "<Method ID='1' Cmd='New'><Field Name='ID'>New</Field><Field Name='FSObjType'>1</Field><Field Name='BaseName'>" + parent + folder + "</Field></Method>" ;
            XmlDocument xmlDoc = new XmlDocument();
            XmlElement elBatch = xmlDoc.CreateElement("Batch");
            elBatch.SetAttribute("OnError", "Continue");
            elBatch.SetAttribute("ListVersion", "1");
            elBatch.SetAttribute("ViewName", "");
            elBatch.InnerXml = CreateSubFolder;

            try
            {
                setupWebServices();

                XElement ret = sp.UpdateListItems(getImageListName(), XElement.Parse(elBatch.OuterXml));
            }
            catch (Exception ex) { MessageBox.Show(getExceptionDetail(ex)); }
        }

        private string getExceptionDetail(Exception ex)
        {
            FaultException faultException = (FaultException)ex;
            MessageFault msgFault = faultException.CreateMessageFault();
            XmlElement elm = msgFault.GetDetail<XmlElement>();
            return elm.InnerText;
        }


        private static string getOwsItemId(XElement xe)
        {
            string owsItemId = "";
            foreach (XElement x2 in xe.Descendants())
            {
                // Siamo in Result

                foreach (XElement x3 in x2.Descendants())
                {
                    // Siamo nei risultati
                    if (x3.Name.LocalName == "row")
                        foreach (XAttribute att in x3.Attributes())
                            if (att.Name == "ows_ID")
                                owsItemId = att.Value;
                }

            }
            return owsItemId;
        }

        private string uploadImages(string folderPath, string htmlBody, string folder)
        {
            createFolder(getRootImageFolder(false), "");

            //folder += "_img";
            DirectoryInfo dir = new DirectoryInfo(folderPath);
            if(dir.Exists)
            { 
                foreach(FileInfo fi in dir.GetFiles())
                {
                    byte[] b = System.IO.File.ReadAllBytes(fi.FullName);
                    createFolder(folder, getRootImageFolder());

                    XElement ximg = imag.Upload(getImageListName(), getRootImageFolder() + folder, b, fi.Name, false);
                    htmlBody = htmlBody.Replace(dir.Name + "/" + fi.Name,  ManageFinalSlash(true, getSiteUrl()) + getImageListName() + "/" + getRootImageFolder() + folder + "/" + fi.Name);
                }
                dir.Delete(true);
            }
            return htmlBody;
        }

        private string getHTML(Word.Selection selection, string titel)
        {
            Word.Document x3 = this.Application.Documents.Add();
            x3.Words.First.InsertXML(selection.XML);
            string filename = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".html";
            x3.SaveAs2(filename, Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatFilteredHTML);
            x3.Close();
            byte[] html = System.IO.File.ReadAllBytes(filename);
            Encoding wind1252 = Encoding.GetEncoding(1252);
            Encoding utf8 = Encoding.UTF8;
            //byte[] wind1252Bytes = wind1252.GetBytes(html);
            byte[] utf8Bytes = Encoding.Convert(wind1252, utf8, html);
            string utf8String = Encoding.UTF8.GetString(utf8Bytes);
            System.IO.File.Delete(filename);
            return uploadImages(filename.Replace(".html", "_file"), utf8String, titel);
        }

        string convertCSS(string inp)
        {
            Hashtable ht = new Hashtable();
            ht.Add("MsoNormal", "margin-top:0cm;margin-right:0cm;margin-bottom:8.0pt;margin-left:0cm;line-height:107%;font-size:11.0pt;font-family:\"Calibri\",\"sans-serif\";");
            ht.Add("MsoListParagraph", "margin-top:0cm;margin-right:0cm;margin-bottom:10.0pt;margin-left:36.0pt;line-height:115%;font-size:11.0pt;font-family:\"Calibri\",\"sans-serif\";");
            ht.Add("MsoListParagraphCxSpFirst", "margin-top:0cm;margin-right:0cm;margin-bottom:0cm;margin-left:36.0pt;margin-bottom:.0001pt;line-height:115%;font-size:11.0pt;font-family:\"Calibri\",\"sans-serif\";");
            ht.Add("MsoListParagraphCxSpMiddle", "margin-top:0cm;margin-right:0cm;margin-bottom:0cm;margin-left:36.0pt;margin-bottom:.0001pt;line-height:115%;font-size:11.0pt;font-family:\"Calibri\",\"sans-serif\";");
            ht.Add("MsoListParagraphCxSpLast", "margin-top:0cm;margin-right:0cm;margin-bottom:10.0pt;margin-left:36.0pt;line-height:115%;font-size:11.0pt;font-family:\"Calibri\",\"sans-serif\";");
            ht.Add("MsoChpDefault", "font-family:\"Calibri\",\"sans-serif\";");
            ht.Add("MsoPapDefault", "margin-bottom:8.0pt;line-height:107%;");

            foreach(DictionaryEntry hs in ht)
            {
                inp = inp.Replace("class=\""+hs.Key+"\"", "style=\""+hs.Value+"\"");
                inp = inp.Replace("class=" + hs.Key + "", "style=\"" + hs.Value + "\"");
            }
            return inp;
        }

        #region Von VSTO generierter Code

        /// <summary>
        /// Erforderliche Methode für die Designerunterstützung.
        /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }
        
        #endregion
    }
}
